提及uni-app + Pinia + TailwindCSS 配置过程,当事人:再也不配了

记一下我在配置uni-app + Pinia + TailwindCSS的过程中遇到的一些问题和解决方法,顺便吐槽一下这个过程。

需要先声明一下,我用过Vue,想开发微信小程序,所以在我最近的工程里,我被迫选择了uni-app。叠甲结束。

我不想看你啰嗦,给老子上预制菜

我用JavaScript:

1
npx degit GalaxyLHN/uni-preset-vue-pinia-tailwindcss#vite <文件夹名>

我用TypeScript:

1
npx degit GalaxyLHN/uni-preset-vue-pinia-tailwindcss#vite-ts <文件夹名>

以上和直接去GitHub下载是等效的,如果终端用不了可以从网页下载,然后直接把文件夹名字改掉。记得下载对应分支,不要下载master,我放在那只是因为我删不掉。

从这一步开始,不建议用npm,直接用pnpm来安装依赖,因为npm遇到这个工程中可以忽略的历史遗留问题就会直接卡死。接下来安装依赖:

1
pnpm install

然后就可以运行了。

1
pnpm run dev:mp-weixin

我不想看你罗嗦,给老子上教程

这份教程可以让你知其然,不保证知其所以然。这是我对这个配置过程的总结,希望在一定时间范围内对你有帮助。

创建工程

uni-app提供了一个工程模板,可以一键下载官方存放在GitHub的代码模板:

1
npx degit dcloudio/uni-preset-vue#vite <文件夹名>

想使用TypeScript的话需要在这段命令上稍加改动:

1
npx degit dcloudio/uni-preset-vue#vite-ts <文件夹名>

以上和直接去GitHub下载是等效的,如果终端用不了可以从网页下载,然后直接把文件夹名字改掉。

从这一步开始,不建议用npm,直接用pnpm来安装依赖,因为npm遇到这个工程中可以忽略的历史遗留问题就会直接卡死。接下来安装依赖:

1
pnpm install

安装和配置TailwindCSS

不要安装最新版本的TailwindCSS,直接安装v3,以及后面会用来解析scss的sass:

1
pnpm i -D tailwindcss@3 postcss autoprefixer weapp-tailwindcss sass

生成并修改tailwind.config.jspostcss.config.js

1
npx tailwindcss init -p
1
2
3
4
5
6
7
8
9
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
// 核心:让 Tailwind 扫描所有 Vue 文件
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
corePlugins: {
preflight: false, // 不配置会弹警告
},
};
1
2
3
4
5
6
7
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

编辑vite.config.jsvite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 其他引入...
import { UnifiedViteWeappTailwindcssPlugin as uvwt } from "weapp-tailwindcss/vite";
import tailwindcss from "tailwindcss";
import autoprefixer from "autoprefixer";

export default defineConfig({
plugins: [
// 其他插件...
uvwt({
rem2rpx: true, // 自动将 rem 转换为小程序专用的 rpx,可按需配置
}),
],
css: {
postcss: {
plugins: [tailwindcss(), autoprefixer()],
},
},
});

App.vue同级创建并引用style.scss

1
2
3
@tailwind base;
@tailwind components;
@tailwind utilities;
1
2
3
<style>
@import "./style.scss";
</style>

安装和配置Pinia

安装Pinia以及持久化工具:

1
pnpm i pinia pinia-plugin-persistedstate

src/main.jssrc/main.ts中引入并注册Pinia:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createSSRApp } from "vue";
import App from "./App.vue";
import * as Pinia from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
export function createApp() {
const app = createSSRApp(App);
const pinia = Pinia.createPinia();
pinia.use(piniaPluginPersistedstate); // 使用持久化插件,确保用户登录信息等数据不会因为关掉小程序而丢失
app.use(pinia);
return {
app,
Pinia,
};
}

到这里配置已经完成了。如果要在微信小程序中使用Pinia的持久化功能,需要在定义store的时候进行特殊配置:

1
2
3
4
5
6
7
8
9
10
11
12
// 引入
export const useCounterStore = defineStore('counter', () => {
// 定义状态和方法
}, {
persist: {
storage: {
// 抹平 H5 和小程序的 API 差异
getItem: (key) => uni.getStorageSync(key),
setItem: (key, value) => uni.setStorageSync(key, value),
},
},
});

运行

然后就可以运行了。

1
pnpm run dev:mp-weixin

我遇到的坑

使用uni-app工程模板

uni-app提供了一个工程模板,可以一键下载官方存放在GitHub的代码模板:

1
npx degit dcloudio/uni-preset-vue#vite my-vue3-project

我想使用TypeScript,所以就有了第一个坑点:这是一个JavaScript工程模板,官方虽然有,但并没有给出他们TypeScript模板的下载方式:

1
npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project

以上和直接去GitHub下载是等效的,如果终端用不了可以从网页下载。

安装和配置TailwindCSS

Gimini认为不会产生任何问题的流程

TailwindCSS的兼容性问题非常大。我首先下载了最新版本,即v4。weapp-tailwindcss是针对小程序的转译工具,可以把这个用在网页端的技术迁移到小程序:

1
pnpm i -D tailwindcss postcss autoprefixer weapp-tailwindcss

接下来是初始化TailwindCSS:

1
npx tailwindcss init -p

然后在tailwind.config.js中配置内容,这段完全是当时Gemini生成的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/** @type {import('tailwindcss').Config} */
module.exports = {
// 确保涵盖所有 vue 文件
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {
colors: {
primary: "#2B58FF",
secondary: "#F4F7FF",
},
},
},
// 禁用预设,避免与小程序基础样式冲突
corePlugins: {
preflight: false,
},
};

然后是在vite.config.ts中添加转译工具作为插件:

1
2
3
4
5
6
7
8
9
10
// 其他引入...
import { UnifiedViteWeappTailwindcssPlugin as uvwt } from "weapp-tailwindcss/vite";
export default defineConfig({
plugins: [
// 其他插件...
uvwt({
rem2rpx: true, // 自动将 rem 转换为小程序专用的 rpx
}),
],
});

最后是创建style.css并在App.vue中引入:

1
2
3
@tailwind base;
@tailwind components;
@tailwind utilities;

坑点:cssEntries

首先是一个编译报错:

1
[tailwindcss@4] 未检测到 cssEntries 配置。请传入包含 tailwindcss 引用的 CSS 绝对路径,例如 cssEntries: ["/absolute/path/to/src/app.css"],否则 tailwindcss 生成的类名不会参与转译。

遵循缺啥补啥的原则,Gemini建议我去在vite.config.ts里面加一个cssEntries参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 其他引入...
import path from "path"; // 记得引入 path 模块

export default defineConfig({
plugins: [
uni(),
uvwt({
// 核心修正:告诉插件你的 Tailwind 样式入口在哪里
// path.resolve 会生成插件要求的“绝对路径”
cssEntries: [path.resolve(__dirname, "./src/styles/main.css")],
rem2rpx: true,
}),
],
});

Gemini顺便让我把style.css也更新了一下。这段神秘代码甚至在我的IDE里面划红线了:

1
2
3
4
5
6
7
8
9
10
11
12
/* Tailwind v4 的标准引入方式 */
@import "tailwindcss";

/* 如果你有一些旧的自定义配置,v4 推荐直接在 CSS 里写 @theme */
@theme {
--color-primary: #2b58ff;
}

/* 针对小程序的全局微调 */
page {
background-color: #f8f8f8;
}

坑点:没有postcss包

配好了cssEntries之后,编译又报了一个错:

1
... 无法定位 Tailwind CSS 包 "@tailwindcss/postcss" ...

Gemini认为v4不需要postcss包才对,建议我降级到v3。但我没有降级,想着应该没啥大事:

1
pnpm i -D @tailwindcss/postcss postcss

顺便也写了一个postcss.config.js

1
2
3
4
5
6
export default {
plugins: {
"@tailwindcss/postcss": {}, // 告诉 PostCSS 使用 v4 引擎
autoprefixer: {},
},
};

我还按Gemini的建议把vite.config.ts里的cssEntries注释掉了。

坑点:你不能使用TailwindCSS v4

想着终于解决了,编译又是当头一棒:

1
[plugin:vite:css] [postcss] postcss-import: <工程路径>\node_modules\tailwindcss\dist\lib.mjs:1:8: Unknown word a,b,c,d,e,f

没招了,基本可以断定是TailwindCSS v4和uni-app或者是别的啥的兼容性问题了。于是退回到v3并生成了tailwind.config.js

1
2
3
pnpm remove tailwindcss @tailwindcss/postcss @tailwindcss/vite
pnpm i -D tailwindcss@3 postcss autoprefixer weapp-tailwindcss
npx tailwindcss init -p
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {
colors: {
primary: "#2B58FF",
},
},
},
corePlugins: {
preflight: false,
},
};

坑点:@tailwind无法被正确解析

编译总算通过了,让我们看看微信开发者工具。哦我的老天,生成的wxss文件里面

1
2
3
@tailwind base;
@tailwind components;
@tailwind utilities;

这一坨微信那边没办法解析。

Gemini建议我把style.css改成style.scss,这里需要装一个依赖:

1
pnpm i -D sass

还没解决问题。我试着改用@import来引入TailwindCSS的样式,实际上不用这么做,所以结果还是不行:

1
2
3
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

最后的解决方法是把PostCSS直接怼进vite.config.ts里面:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 其他引入...
import tailwindcss from "tailwindcss";
import autoprefixer from "autoprefixer";

export default defineConfig({
// 其他配置...
// 强制显式配置 CSS 处理
css: {
postcss: {
plugins: [tailwindcss(), autoprefixer()],
},
},
});

终于样式正常了。

persist跨端的正确用法

Pinia的配置过程相对来说比较顺利,但在我收拾完TailwindCSS的时候,Gemini主动写了一个测试文件来验证Pinia和TailwindCSS是否能正常工作。这时我发现,Pinia的状态管理功能完全失效了,组件里无法访问到store的数据。想去h5端看看调试,结果非常意外的是,h5端是正常的,只有微信小程序里不行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { defineStore } from "pinia";

export const useCounterStore = defineStore(
"counter",
() => {
const count = ref(0);
const increment = () => count.value++;

return { count, increment };
},
{
persist: true, // 还记得吗?这会让你的数字在关掉小程序后再打开依然存在
},
);

发现把persist: true注释掉之后就好了,所以是小程序的方言导致这个配置失效了。Gemini帮我更新了这一块的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 引入
export const useCounterStore = defineStore(
"counter",
() => {
// 定义状态和方法
},
{
persist: {
storage: {
// 抹平 H5 和小程序的 API 差异
getItem: (key) => uni.getStorageSync(key),
setItem: (key, value) => uni.setStorageSync(key, value),
},
},
},
);

这样Pinia的状态管理持久化功能在微信小程序里也能正常工作了。